package com.paul.security;

import org.apache.commons.lang.SerializationUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import java.io.Serializable;
import java.util.*;

/**
 * Created by dell on 2016/3/23.
 */
public class RedisCache<K extends Serializable, V extends Serializable> implements Cache<K, V> {

    private final String name="rediscache";

    private String keyPrefix="shiro_redis_cache:";

    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public V get(K k) throws CacheException {
        try {
            if (k == null) {
                return null;
            }else{
                String key = getByteKey(k);
                V rawValue=(V)redisTemplate.opsForValue().get(key);
                return rawValue;
            }
        } catch (Throwable t) {
            throw new CacheException(t);
        }
    }

    @Override
    public V put(K k, V v) throws CacheException {
        String key = getByteKey(k);
        redisTemplate.opsForValue().set(key,v);
        return v;
    }

    @Override
    public V remove(K k) throws CacheException {
        String key = getByteKey(k);
        V value=(V)redisTemplate.opsForValue().get(key);
        redisTemplate.delete(key);
        return value;
    }

    @Override
    public void clear() throws CacheException {
        Set<String> bytesKeys=redisTemplate.keys(this.keyPrefix+"*");
        redisTemplate.delete(bytesKeys);
    }

    @Override
    public int size() {
        Set<String> bytesKeys=redisTemplate.keys(this.keyPrefix+"*");
        return bytesKeys.size();
    }

    @Override
    public Set<K> keys() {
        Set<String> bytesKeys=redisTemplate.keys(this.keyPrefix+"*");
        Set<K> sets=new HashSet<K>();
        return  sets;
    }

    @Override
    public Collection<V> values() {
        Set<String> bytesKeys=redisTemplate.keys(this.keyPrefix+"*");
        List<V> values = new ArrayList<V>(bytesKeys.size());
        for(String str :bytesKeys){
          V vlue=  (V)redisTemplate.opsForValue().get(str);
          values.add(vlue);
        }
        return  values;
    }

    private String getByteKey(K key){
        if(key instanceof String){
            String preKey = this.keyPrefix + key;
            return preKey;
        }else{
            byte[] bytes= SerializationUtils.serialize(key);
            return this.keyPrefix+bytes.toString();
        }
    }
}
